<?php
declare(strict_types=1);

namespace app\api\service;

use app\common\library\Pay;
use app\common\model\delivery\CardLog;
use app\common\model\delivery\ChannelGird;
use app\common\model\delivery\ChannelOrder as ChannelOrderModel;
use app\common\model\delivery\Coupon;
use app\common\model\delivery\CouponList;
use app\common\model\delivery\CouponVerify;
use app\common\model\delivery\Customer;
use app\common\model\delivery\Driver;
use app\common\model\delivery\MonthBill;
use app\common\model\delivery\PayLog;
use app\common\service\BaseService;
use app\common\service\msg\WechatMsg;
use think\facade\Db;

class ChannelOrder extends BaseService
{
    private $channel_id;
    private $customer_id;
    private $user_id;
    private $goods_id;
    private $spec_id;
    private $address_id;
    private $number;
    private $pay_type;
    private $order_type;
    private $delivery_day;
    private $coupon_id;
    private $bill_driver_id;
    private $updatetime;
    private $platform;
    private $remark;

    public function createOrder()
    {
        $customer=$this->getObj(Customer::class);
        $data=[];
        $data['channel_id']=$this->channel_id;
        $data['customer_id']=$this->customer_id;
        $data['goods_id']=$this->goods_id;
        $data['spec_id']=$this->spec_id;
        $data['user_id']=$this->user_id;
        $data['order_no']=create_out_trade_no();
        $data['order_type']=$this->order_type;
        $data['pay_type']=$this->pay_type;
        $data['address_id']=$this->address_id;
        $data['remark']=$this->remark;
        $data['bill_driver_id']=$this->bill_driver_id;
        $data['price']=0;
        $goodsname='';
        foreach ($customer->goods as $value){
            if($value['goods_id']==$this->goods_id && $value['spec_id']==$this->spec_id){
                $data['price']=$value['spec_price'];
                $goodsname=$value['goods_name'];
                break;
            }
        }
        if(!$data['price']){
            throw new SystemException('商品价格异常！');
        }
        $data['number']=$this->number;
        $data['total_money']=$data['price']*$this->number;
        $data['pay_money']=$data['price']*$this->number;
        $data['delivery_day']=($this->delivery_day==0 || $this->delivery_day==1 || $this->delivery_day==3)?date('Y-m-d',time()):date('Y-m-d',strtotime("+1 day"));
        $data['hurry']=($this->delivery_day==0)?1:0;
        $data['gird_id']=$customer->gird_id;
        if($this->pay_type==ChannelOrderModel::PAY_TYPE('账单月结')){
            $data['is_pay']=1;
        }else{
            $data['is_pay']=0;
        }
        //处理优惠券
        if($this->coupon_id){
            $coupon=$this->getObj(Coupon::class);
            switch ($coupon['type']){
                case 'cash':
                    $pay_money=$data['pay_money']-$coupon['cash'];
                    $coupon_money=($coupon['cash']>=$data['pay_money'])?$data['pay_money']:$coupon['cash'];
                    $data['pay_money']=$pay_money>0?$pay_money:0;
                    $data['coupon_money']=$coupon_money;
                    break;
                case 'discount':
                    $data['pay_money']=$data['pay_money']*$coupon['discount']/10;
                    $data['coupon_money']=$data['pay_money']*(10-$coupon['discount'])/10;
                    break;
                case 'full_minus':
                    $full_minus=json_decode($coupon['full_minus'],true);
                    foreach ($full_minus as $man=>$jian){
                        $man=floatval($man);
                        $jian=floatval($jian);
                        if($data['pay_money']>=$man && $jian>$data['coupon_money']){
                            $data['coupon_money']=$jian;
                        }
                    }
                    $data['pay_money']=$data['pay_money']-$data['coupon_money'];
                    break;
                case 'goods':
                    $data['coupon_money']=$data['pay_money'];
                    $data['pay_money']=0;
                    $data['pay_type']=ChannelOrderModel::PAY_TYPE('商品券支付');
                    $data['is_pay']=1;
                    break;
                case 'card':
                    $couponlist=$this->getObj(CouponList::class);
                    if($couponlist->balance<$data['pay_money']){
                        throw new SystemException('【'.$coupon['title'].'】余额不足！');
                    }
                    $data['coupon_money']=$data['pay_money'];
                    $data['pay_money']=0;
                    $data['pay_type']=ChannelOrderModel::PAY_TYPE('会员卡余额支付');
                    $data['is_pay']=1;
                    break;
            }
        }
        $payinfo='';
        Db::startTrans();
        try{
            if($data['pay_type']==ChannelOrderModel::PAY_TYPE('商品券支付') || $data['pay_type']==ChannelOrderModel::PAY_TYPE('会员卡余额支付')){
                $log=new PayLog();
                $log->save([
                    'user_id'=>$this->user_id,
                    'type'=>PayLog::TYPE('支付订单'),
                    'pay_price'=>$data['total_money'],
                    'out_trade_no'=>$data['order_no'],
                    'pay_status'=>1,
                    'pay_time'=>date('Y-m-d H:i:s',time())
                ]);
                $data['pay_id']=$log->id;
            }
            $order=new ChannelOrderModel();
            $order->save($data);
            if($order->pay_type=='wechat' && $order->pay_money>0){
                if($this->bill_driver_id){
                    throw new SystemException('代客下单，暂不支持微信支付！');
                }
                $payinfo=(new Pay($customer->channel->sub_mch_id))->unifiedorder($order->order_no,$this->user_id,$order->pay_money,'用户下单购买-'.$goodsname,PayLog::TYPE('支付订单'),$this->platform);
            }
            if(!$payinfo && $order->hurry && $order->gird_id){
                $gird=ChannelGird::find($order->gird_id);
                if($gird->drivers){
                    $userid=Driver::whereIn('id',$gird->drivers)->column('user_id');
                    foreach ($userid as $id){
                        WechatMsg::hurryOrderDelivery($id,$order);
                    }
                }
            }
            if($order->coupon_money>0) {
                $coupon=$this->getObj(Coupon::class);
                $couponlist=$this->getObj(CouponList::class);
                $verify=[
                    'coupon_id'=>$coupon->id,
                    'coupon_list_id'=>$couponlist->id,
                    'order_table'=>'channel_order',
                    'order_id'=>$order->id,
                    'money'=>$order->coupon_money,
                    'verify_time'=>date('Y-m-d H:i:s',time())
                ];
                CouponVerify::create($verify);
                if(!$payinfo){
                    switch ($coupon['type']) {
                        case 'cash':
                        case 'discount':
                        case 'full_minus':
                        case 'goods':
                            $couponlist->take=$couponlist->take+$this->number;
                            $couponlist->save();
                            break;
                        case 'card':
                            CardLog::addLog($couponlist->id,'minus',$order->coupon_money,$order->order_no,'用户下单扣除余额');
                            break;
                    }
                    $coupon->take=$coupon->take+1;
                    $coupon->save();
                }
            }
            if($this->delivery_day==3){
               $order->receive();
            }
            Db::commit();
        }catch (\Exception $e) {
            Db::rollback();
            throw new SystemException($e->getMessage());
        }
        return $payinfo;
    }

    protected function init()
    {
        $customer=Customer::find($this->customer_id);
        if(!$customer){
            throw new SystemException('客户不存在！');
        }
        if($customer->status!='normal'){
            throw new SystemException('客户状态异常！');
        }
        if($this->coupon_id){
            $coupon=CouponList::with(['coupon'])->find($this->coupon_id);
            if(!$coupon){
                throw new SystemException('卡卷不存在！');
            }
            $couponType=$coupon->coupon['type'];
            $couponTitle=$coupon->coupon['title'];
            switch ($couponType) {
                case 'cash':
                case 'discount':
                case 'full_minus':
                case 'goods':
                    if ($coupon->total - $coupon->take < $this->number) {
                        throw new SystemException('【'.$couponTitle.'】兑换次数不足！');
                    }
                    break;
            }
            if($coupon->expire_time<time()){
                throw new SystemException('【'.$couponTitle.'】已经过期！');
            }
            if(!CouponList::checkGoods($coupon,$this->goods_id)){
                throw new SystemException('【'.$couponTitle.'】不适用于该商品！');
            }
            $this->setObj(CouponList::class,$coupon);
            $this->setObj(Coupon::class,$coupon->coupon);
        }
        if($this->order_type==ChannelOrderModel::ORDER_TYPE('用户下单') && $customer->updatetime!=$this->updatetime){
            throw new CustomerRefreshException('客户信息被修改，请重新下单');
        }
        if($this->pay_type==ChannelOrderModel::PAY_TYPE('账单月结')){
            $bill=MonthBill::where(['customer_id'=>$this->customer_id,'goods_id'=>$this->goods_id,'is_pay'=>0])->find();
            if($bill){
                throw new BillUnPayedException('有账单未支付完成，请先支付完成再下单');
            }
        }
        $customer->goods=Customer::parseGoods($customer->goods,$customer->channel);
        $this->setObj(Customer::class,$customer);
        if($this->delivery_day==3 && $customer->user_id){
           $this->user_id=explode(',',$customer->user_id)[0];
        }
    }
}

class SystemException extends \Exception{}
class CustomerRefreshException extends \Exception{}
class BillUnPayedException extends \Exception{}